<?php
/**
 * Author: xx.com
 */
namespace Shop\Controller;

class WxpayController extends BaseController
{
    /*
     * 配置参数
     */
    public function __construct() {
        $this->config = C ( 'ZSF_WX_PAY' ); // 引入配置
    }
	
	// 获取预支付订单
	public function testpay() {

	    // 获取支付金额
	    $amount = 0.01;
	    $total = floatval($amount);
	    $paymoney = round($total * 100); // 将元转成分
	    // 验证金额
	    if ($paymoney <= 0) {
	        $res = array('msg'=>'此订单金额无效！','status'=>-1);
	        $this->ajaxReturn($res);
	    }
		
	    
	    $body = $this->config['app_name'].'-' . '退款';
	    $out_trade_no = 'U'.time();
	    $total_fee = $paymoney; // 微信支付 单位为分
	    $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//$this->config ['pay_api']; // "https://api.mch.weixin.qq.com/pay/unifiedorder";
	 
	    //$notify_url = $this->config ["notify_url"];
	    
	    $onoce_str = $this->getRandChar ( 32 );
	
	    $data ["mch_appid"] = $this->config ["app_id"];
        $data ["mchid"] = $this->config ['mch_id'];
        $data ["nonce_str"] = $onoce_str;

        $data ["partner_trade_no"] = $out_trade_no;
        $data ["openid"] = 'oqgev4qxKuZ0OvpbwTQmm9MJH2_8';
        $data['check_name'] = 'NO_CHECK';
        $data['amount'] = $total_fee;
        $data['desc'] = '退款';
        $s = $this->getSign ( $data );
        $data ["sign"] = $s;
	    //$data ["body"] = $body;


	    //$data ["notify_url"] = $notify_url;


	    //$data ["spbill_create_ip"] = $this->get_client_ip ();
	    //$data ["total_fee"] = $total_fee;
	    //$data ["trade_type"] = "JSAPI";
		
		
		

		// p($data);die;
	    $xml = $this->arrayToXml ( $data );
	    $response = $this->postXmlCurl ( $xml, $url );
		

	  
	    $re = $this->xmlstr_to_array ( $response );
		//p($re);die;

	    if ($re ['return_code'] == 'FAIL') {
	        $res = array('msg'=>'获取失败','status'=>-1,'result'=>$re['return_msg']);
	        $this->ajaxReturn($res);
	    }
	    
	    // 将微信返回的结果xml转成数组
	    $res = array('msg'=>'返回签名','status'=>1,'result'=>$re);
	    $this->ajaxReturn($res);
	     
	}

    public function testpay2() {

        // 获取支付金额
        $amount = 0.01;
        $total = floatval($amount);
        $paymoney = round($total * 100); // 将元转成分
        // 验证金额
        if ($paymoney <= 0) {
            $res = array('msg'=>'此订单金额无效！','status'=>-1);
            $this->ajaxReturn($res);
        }


        $body = $this->config['app_name'].'-' . '退款';
        $out_trade_no = 'U'.time();
        $total_fee = $paymoney; // 微信支付 单位为分
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
        //"https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//$this->config ['pay_api']; // "https://api.mch.weixin.qq.com/pay/unifiedorder";

        //$notify_url = $this->config ["notify_url"];

        $onoce_str = $this->getRandChar ( 32 );

        $data ["appid"] = $this->config ["app_id"];
        $data ["mch_id"] = $this->config ['mch_id'];
        $data ["nonce_str"] = $onoce_str;
        $data['sign_type'] = 'MD5';
        $data['transaction_id'] = '4200000543202005079382142586';
        $data['out_refund_no'] = $out_trade_no;
        $data['total_fee'] = 1;
        $data['refund_fee'] = 1;


        //$data ["partner_trade_no"] = $out_trade_no;
        //$data ["openid"] = 'oqgev4qxKuZ0OvpbwTQmm9MJH2_8';
        //$data['check_name'] = 'NO_CHECK';
        //$data['amount'] = $total_fee;
        $data['refund_desc'] = '退款';
        $s = $this->getSign ( $data );
        $data ["sign"] = $s;

        $xml = $this->arrayToXml ( $data );
        $response = $this->postXmlCurl ( $xml, $url );



        $re = $this->xmlstr_to_array ( $response );
        //p($re);die;

        if ($re ['return_code'] == 'FAIL') {
            $res = array('msg'=>'获取失败','status'=>-1,'result'=>$re['return_msg']);
            $this->ajaxReturn($res);
        }

        // 将微信返回的结果xml转成数组
        $res = array('msg'=>'返回签名','status'=>1,'result'=>$re);
        $this->ajaxReturn($res);

    }


    /**
     * 申请退款微信打款
     * @param int $id
     * @return array
     */
    public function drawback_pay($id=0){
        if($id <= 0){
            $res = array('status'=>0, 'msg'=>'退款申请id有误','result'=>'');
            return $res;
        }
        $drawbackModel = M('drawback');
        $drawback_info = $drawbackModel->where(array('id'=>$id))->find();
        if(!$drawback_info){
            $res = array('status'=>0, 'msg'=>'退款申请信息有误','result'=>'');
            return $res;
        }
        $order_info = M('order')->field('third_trade_no, order_amount')
            ->where(array('order_id'=>$drawback_info['order_id']))->find();
        $amount = $drawback_info['money'];
        $total = floatval($amount);
        $paymoney = round($total * 100); // 将元转成分
        // 验证金额
        if ($paymoney <= 0) {
            $res = array('msg'=>'此订单金额无效！','status'=>-1);
            return $res;
        }

        //$body = $this->config['app_name'].'-' . '退款';

        if($drawback_info['out_refund_no']){
            $partner_trade_no = $drawback_info['out_refund_no'];
        }else{
            $partner_trade_no = 'Draw'.get_rand_str(6,1,1);
            $drawbackModel->where(array('id'=>$id))->setField('out_refund_no', $partner_trade_no);
        }
        //$total_fee = $paymoney; // 微信支付 单位为分
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';

        //$notify_url = $this->config ["notify_url"];

        $onoce_str = $this->getRandChar ( 32 );

        $data ["appid"] = $this->config ["app_id"];
        $data ["mch_id"] = $this->config ['mch_id'];
        $data ["nonce_str"] = $onoce_str;
        $data['sign_type'] = 'MD5';
        $data['transaction_id'] = $order_info['third_trade_no'];
        $data['out_refund_no'] = $partner_trade_no;
        $data['total_fee'] = 1;// $order_info['order_amount'];测试时1分
        $data['refund_fee'] = 1;//$paymoney;  测试时1分


        //$data ["partner_trade_no"] = $out_trade_no;
        //$data ["openid"] = 'oqgev4qxKuZ0OvpbwTQmm9MJH2_8';
        //$data['check_name'] = 'NO_CHECK';
        //$data['amount'] = $total_fee;
        $data['refund_desc'] = '退款';
        $s = $this->getSign ( $data );
        $data ["sign"] = $s;

        $xml = $this->arrayToXml ( $data );
        $response = $this->postXmlCurl ( $xml, $url );


        $re = $this->xmlstr_to_array ( $response );

        if ($re ['return_code'] == 'SUCCESS' && $re['result_code'] == 'SUCCESS') {
            $res = array('msg'=>$re['return_msg'],'status'=> 1,'result'=>$re);
            return $res;
        }

        $res = array('msg'=>$re['err_code_des'],'status'=>0,'result'=>$re);
        return $res;
    }

    /**
     * 提现打款
     * @param int $id
     * @return array
     */
	public function withdraw_pay($id=0){
        if($id <= 0){
            $res = array('status'=>0, 'msg'=>'提现申请id有误','result'=>'');
            return $res;
        }
        $withdrawalsShopModel = M('withdrawals_shop');
        $withdraw_info = $withdrawalsShopModel->where(array('id'=>$id))->find();
        if(!$withdraw_info){
            $res = array('status'=>0, 'msg'=>'提现申请信息有误','result'=>'');
            return $res;
        }

        $amount = $withdraw_info['money'];
        $total = floatval($amount);
        $paymoney = round($total * 100); // 将元转成分
        // 验证金额
        if ($paymoney <= 0) {
            $res = array('msg'=>'此订单金额无效！','status'=>-1);
            return $res;
        }

        //$body = $this->config['app_name'].'-' . '退款';
        if($withdraw_info['partner_trade_no']){
            $partner_trade_no = $withdraw_info['partner_trade_no'];
        }else{
            $partner_trade_no = 'With'.get_rand_str(6,1,1);
            $withdrawalsShopModel->where(array('id'=>$id))->setField('partner_trade_no', $partner_trade_no);
        }

        $total_fee = $paymoney; // 微信支付 单位为分
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//$this->config ['pay_api']; // "https://api.mch.weixin.qq.com/pay/unifiedorder";

        //$notify_url = $this->config ["notify_url"];

        $onoce_str = $this->getRandChar ( 32 );

        $data ["mch_appid"] = $this->config ["app_id"];
        $data ["mchid"] = $this->config ['mch_id'];
        $data ["nonce_str"] = $onoce_str;

        $data ["partner_trade_no"] = $partner_trade_no;


        $user_info = M('users')->field('openid')->where(array('user_id'=>$withdraw_info['user_id']))->find();
        if(!$user_info){
            $res = array('msg'=>'提现用户不存在','status'=> 0,'result'=>'');
            return $res;
        }
        if(!$user_info['openid']){
            $res = array('msg'=>'提现用户openid为空，请先登陆小程序','status'=> 0,'result'=>'');
            return $res;
        }
        $open_id = $user_info['openid'];

        $data ["openid"] = $open_id;//'oqgev4qxKuZ0OvpbwTQmm9MJH2_8';
        $data['check_name'] = 'NO_CHECK';
        $data['amount'] = $total_fee;
        $data['desc'] = '商铺提现';
        $s = $this->getSign ( $data );
        $data ["sign"] = $s;


        $xml = $this->arrayToXml ( $data );
        $response = $this->postXmlCurl ( $xml, $url );

        $re = $this->xmlstr_to_array ( $response );

        if ($re ['return_code'] == 'SUCCESS' && $re['result_code'] == 'SUCCESS') {
            $res = array('msg'=>$re['return_msg'],'status'=> 1,'result'=>$re);
            return $res;
        }

        $res = array('msg'=>$re['err_code_des'],'status'=>0,'result'=>$re);
        return $res;
    }

	/*
	 * 生成签名
	 */
	function getSigns($Obj) {
		// p($this->config ['key']);die;
	    foreach ( $Obj as $k => $v ) {
	        $Parameters [$k] = $v;
	    }
		// p($Parameters);die;
	    // 签名步骤一：按字典序排序参数
	    ksort ( $Parameters );
	    $String = $this->formatBizQueryParaMaps ( $Parameters, false );
	    // echo "【string】 =".$String."</br>";
	    // 签名步骤二：在string后加入KEY
	    $String = $String . "&key=" . $this->config ['key'];
	    // echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";die;
	    // 签名步骤三：MD5加密
	    $result_ = strtoupper ( md5 ( $String ) );
	    return $result_;
	}
    
    /*
     * 生成签名
     */
    function getSign($Obj) {
		// p($this->config ['key']);die;
        foreach ( $Obj as $k => $v ) {
            $Parameters [strtolower ( $k )] = $v;
        }
        // 签名步骤一：按字典序排序参数
        ksort ( $Parameters );
        $String = $this->formatBizQueryParaMap ( $Parameters, false );
        // echo "【string】 =".$String."</br>";
        // 签名步骤二：在string后加入KEY
        $String = $String . "&key=" . $this->config ['key'];
        // echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";die;
        // 签名步骤三：MD5加密
        $result_ = strtoupper ( md5 ( $String ) );
        return $result_;
    }
    
    // 获取指定长度的随机字符串
    function getRandChar($length) {
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen ( $strPol ) - 1;
        
        for($i = 0; $i < $length; $i ++) {
            $str .= $strPol [rand ( 0, $max )]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
        }
        
        return $str;
    }
    
    // 数组转xml
    function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ( $arr as $key => $val ) {
            if (is_numeric ( $val )) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }
    
    // post https请求，CURLOPT_POSTFIELDS xml格式
    function postXmlCurl($xml, $url, $second = 30) {
        // 初始化curl
        $ch = curl_init ();
        // 超时时间
        curl_setopt ( $ch, CURLOPT_TIMEOUT, $second );
        // 这里设置代理，如果有的话
        // curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        // curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
        // 设置header
        curl_setopt ( $ch, CURLOPT_HEADER, FALSE );
        // 要求结果为字符串且输出到屏幕上
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE );
        // post提交方式
        curl_setopt ( $ch, CURLOPT_POST, TRUE );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $xml );

        $isdir = $_SERVER['DOCUMENT_ROOT']."/cert/";//证书位置;绝对路径

        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');//证书类型
        curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
        curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
        curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
        /*curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');*/

        // 运行curl
        $data = curl_exec ( $ch );
        // 返回结果
        if ($data) {
            curl_close ( $ch );
            return $data;
        } else {
            $error = curl_errno ( $ch );
            echo "curl出错，错误码:$error" . "<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close ( $ch );
            return false;
        }
    }
    
    /*
     * 获取当前服务器的IP
     */
    function get_client_ip() {
        if ($_SERVER ['REMOTE_ADDR']) {
            $cip = $_SERVER ['REMOTE_ADDR'];
        } elseif (getenv ( "REMOTE_ADDR" )) {
            $cip = getenv ( "REMOTE_ADDR" );
        } elseif (getenv ( "HTTP_CLIENT_IP" )) {
            $cip = getenv ( "HTTP_CLIENT_IP" );
        } else {
            $cip = "unknown";
        }
        return $cip;
    }
    
	// 将数组转成uri字符串
	function formatBizQueryParaMaps($paraMap, $urlencode) {
	    $buff = "";
	    ksort ( $paraMap );
	    foreach ( $paraMap as $k => $v ) {
	        if ($urlencode) {
	            $v = urlencode ( $v );
	        }
	        $buff .=  $k . "=" . $v . "&";
	    }
	    $reqPar;
	    if (strlen ( $buff ) > 0) {
	        $reqPar = substr ( $buff, 0, strlen ( $buff ) - 1 );
	    }
	    return $reqPar;
	}
	
    // 将数组转成uri字符串
    function formatBizQueryParaMap($paraMap, $urlencode) {
        $buff = "";
        ksort ( $paraMap );
        foreach ( $paraMap as $k => $v ) {
            if ($urlencode) {
                $v = urlencode ( $v );
            }
            $buff .= strtolower ( $k ) . "=" . $v . "&";
        }
        $reqPar;
        if (strlen ( $buff ) > 0) {
            $reqPar = substr ( $buff, 0, strlen ( $buff ) - 1 );
        }
        return $reqPar;
    }
    
    /**
     * xml转成数组
     */
    function xmlstr_to_array($xmlstr) {
        $doc = new \DOMDocument ();
        $doc->loadXML ( $xmlstr );
        return $this->domnode_to_array ( $doc->documentElement );
    }
    function domnode_to_array($node) {
        $output = array ();
        switch ($node->nodeType) {
            case XML_CDATA_SECTION_NODE :
            case XML_TEXT_NODE :
                $output = trim ( $node->textContent );
                break;
            case XML_ELEMENT_NODE :
                for($i = 0, $m = $node->childNodes->length; $i < $m; $i ++) {
                    $child = $node->childNodes->item ( $i );
                    $v = $this->domnode_to_array ( $child );
                    if (isset ( $child->tagName )) {
                        $t = $child->tagName;
                        if (! isset ( $output [$t] )) {
                            $output [$t] = array ();
                        }
                        $output [$t] [] = $v;
                    } elseif ($v) {
                        $output = ( string ) $v;
                    }
                }
                if (is_array ( $output )) {
                    if ($node->attributes->length) {
                        $a = array ();
                        foreach ( $node->attributes as $attrName => $attrNode ) {
                            $a [$attrName] = ( string ) $attrNode->value;
                        }
                        $output ['@attributes'] = $a;
                    }
                    foreach ( $output as $t => $v ) {
                        if (is_array ( $v ) && count ( $v ) == 1 && $t != '@attributes') {
                            $output [$t] = $v [0];
                        }
                    }
                }
                break;
        }
        return $output;
    }


}

?>